home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Spanish Scene 1
/
SpanishScene1.iso
/
spanish pack n°1 by llfb
/
--llfb--
/
programas
/
sources1.dms
/
sources1.adf
/
SOURCES
/
Disco
/
GetDrive.ASM
< prev
next >
Wrap
Assembly Source File
|
1996-06-04
|
13KB
|
368 lines
** NOTA de ROMAN SOFT/LLFB: Este source requiere los Includes. Búscate un
** disco con ellos y edita el INCDIR poniendo el path completo. Sorry!
** opt o+,ow- ;Devpac 2.0 options
; Before we go to the main subject, I'll give some special information about
; macros in Devpac 2.0.
;
; It is possible to pass a size (byte, word, long) to macros. This is done
; with \0 (the SIZE parameter). If ".b" or ".w" or ".l" is added just after
; the macro name in the macro call then \0 will result in "b" or "w" or "l".
; When no size is given \0 will default to "w".
;
; If you want to pass a parameter that contains spaces then enclose the
; parameter in the macro call between these brackets: <>.
;
; Now we go to the main event...
;
;---------------------------------------------------------------------------
;
; Dr. Maybe presents... >>>> GETDRIVE routine <<<<
;
; I would like to talk about a common problem in programs that write to disk
; at low level (i.e. at bitmap level). For example a simple fast-format
; (initialize) function or installing an intro or picture in the first few
; tracks of a disk.
;
; What happens? Mostly the bitmap structure of the disk is changed. In case
; of initializing a new Root and Bitmap block are written, and in case of a
; bootintro the Bitmap block is changed in such a way that a few tracks are
; allocated for the intro. In both cases the information on the disk has
; changed.
;
; But AmigaDOS must be informed about this. Otherwise AmigaDOS will give
; wrong information about the disk. After initializing the disk will still
; be full or not validated. After a bootintro is installed too much free
; disk space will be showed. The only way to update the disk information is
; to eject and insert it. Another danger is when other tasks want to have
; access to the disk, while your program is writing to the tracks!
;
; I hope the problem is clear. The program must reserve the drive for own
; use, without permitting other tasks to have access to it, and afterwards
; the drive must be returned to system. Well, that's not so difficult, you
; might think, lets look it up in the books. I sought and sought, but didn't
; find. And I think most other Amiga programmers have the same problem. Take
; for example "Bootleg" or "Bootgirl" or "Bootem". Only the Workbench Format
; command does drive-handling nicely. You even get a "DF1:BUSY" icon.
;
; So, what's the only thing left to do for an Amiga freak? Right, you
; guessed it, I disassembled the Format command! Here comes the solution.
;
;---------------------------------------------------------------------------
;
; First find the task that's responsible for giving other tasks access to
; the drive. This is done with the following function from dos.library:
;
; Process_MessagePort = DeviceProc( name )
; d0 d1
;
; Here d1 points to the name of the drive (e.g. 'DF1:',0), which is a
; NULL-terminated string. The returned value in d0 is the MessagePort of the
; DOS process that's controlling the drive. A DOS process is just an exec
; task added with a MessagePort (so we can talk with it) and some DOS
; information (like CLI, Filesystem, etc). All programs loaded from CLI or
; Workbench are DOS processes. Lets take a look at
; "include/libraries/dosextens.i":
;
; STRUCTURE Process,0
; STRUCT pr_Task,TC_SIZE * APTR to exec task
; STRUCT pr_MsgPort,MP_SIZE * This is BPTR address from DOS functions
; WORD pr_Pad * Remaining variables on 4 byte boundaries
; BPTR pr_SegList * Array of seg lists used by this process
; (etc)
;---------------------------------------------------------------------------
;
; Now we send a StandardPacket to the process. A standard packet is just an
; exec message added with some extras, called DOS packet. These extras
; consist of our ReplyPort (to get messages back) and information about the
; command we would like to give to the process. Lets take a look at
; "include/libraries/dosextens.i":
;
; STRUCTURE StandardPacket,0
; STRUCT sp_Msg,MN_SIZE * message
; STRUCT sp_Pkt,dp_SIZEOF * DOS packet
; LABEL sp_SIZEOF
;
; STRUCTURE DosPacket,0
; APTR dp_Link * pointer to EXEC message
; APTR dp_Port * pointer to Reply port for the packet
; * Must be filled in each send.
; LONG dp_Type * See ACTION_... below and
; * 'R' means Read, 'W' means Write to the file system
; LONG dp_Res1 * For file system calls this is the result
; * that would have been returned by the
; * function, e.g. Write ('W') returns actual
; * length written
; LONG dp_Res2 * For file system calls this is what would
; * have been returned by IoErr()
; LONG dp_Arg1
; (etc)
;
; ACTION_INHIBIT EQU 31
; (etc)
;
; The most important element here is dp_Type. This element is filled with
; the command we want to give: ACTION_INHIBIT. For drive reservation we make
; dp_Arg1 = 1 and to return the drive to system we make dp_Arg1 = 0. We can
; do many things with packets. Look at the complete include file yourself!
; After setting up the packet properly, we send it to the process port with
; the exec function PutMsg. Then we GetMsg from drive process back and
; Remove the packet and check error in dp_Res1.
;
;---------------------------------------------------------------------------
;
; Of course you did't understand anything of this bulls..t mambo jambo (I
; kneuw that!), but it works perfectly. Even the "DF0:BUSY" icon appears in
; Workbench!! For full details look at the GetDrive routine below.
;
; GOOD LUCK!
;
; Dr. Maybe
; Postbus 121
; 6850 AD Huissen
; Holland
;
;---------------------------------------------------------------------------
incdir "ram:include/" ;your include directory
include "exec/exec_lib.i"
include "exec/memory.i"
include "exec/ports.i"
include "libraries/dos_lib.i"
include "libraries/dosextens.i"
CALL MACRO ;library function call
jsr _LVO\1(a6)
ENDM
SECTION main,CODE
;**** Open DOS ****
lea _DOSName(pc),a1
moveq #0,d0
CALLEXEC OpenLibrary
move.l d0,_DOSBase
beq quit
;**** Open RAW Window, so I can talk to you. ****
lea rawwindowname(pc),a0
move.l a0,d1
move.l #MODE_OLDFILE,d2
CALLDOS Open
move.l d0,rawwindow
beq quit
;**** Now get drive for own use. ****
lea drivename(pc),a0
moveq #1,d0
bsr GetDrive
beq.s ok
;**** check & display error, and quit ****
lea not_mounted(pc),a0
cmp.b #218,d0
beq.s prt
lea doserror(pc),a0
cmp.b #100,d0
beq.s prt
lea drive_in_use(pc),a0
prt
bsr print
bsr wait_key
bra.s quit
ok
;**** drive disabled successfully ****
lea drive_disabled(pc),a0
bsr print
bsr wait_key
;**** return drive to system
lea drivename(pc),a0
moveq #0,d0
bsr GetDrive
quit
;**** cleanup & exit ****
move.l rawwindow(pc),d1 ;close raw window
beq.s .q1
CALLDOS Close
.q1
move.l _DOSBase(pc),d0 ;close DOS
beq.s .q2
move.l d0,a1
CALLEXEC CloseLibrary
.q2
moveq #0,d0
rts
print
;**** output text in a0 to rawwindow, and wait ****
move.l rawwindow(pc),d1
move.l a0,d2
moveq #-1,d3
.loop
addq.l #1,d3
tst.b (a0)+
bne.s .loop
CALLDOS Write
rts
wait_key
;**** wait for key in raw window *****
move.l rawwindow(pc),d1
lea press_key(pc),a0
bsr print
move.l rawwindow(pc),d1
lea buffer(pc),a0
move.l a0,d2
moveq #1,d3
CALLDOS Read
rts
GetDrive
;***************************************************************************
; *
; Drive disable/enable, (C) Dr. Maybe, Huissen 1990 *
; This routine disables a drive from being used by AmigaDOS, for example *
; if you want to format a disk, or install a bootintro on it. *
; In WorkBench this will result in a "BUSY" icon. *
; Afterwards drive must be returned to system. *
; *
; usage: *
; error = GetDrive( drive_name, action ) *
; d0 a0 d0 *
; *
; drive_name = NULL-terminated string to drive name (e.g. 'DF1:',0) *
; action = 1 to get drive for own use *
; 0 to return drive to system *
; *
; error = 0 if OK *
; 103 if not enough memory *
; 218 if drive not mounted *
; 100 if dos error *
; 126 if disable failed *
; *
;***************************************************************************
move.l d0,d2 ;d2 = action
move.l a0,a3 ;a3 = drive name
;===========================================================================
; Allocate memory for StandardPacket structure #
;===========================================================================
moveq #sp_SIZEOF,d0
move.l #MEMF_CLEAR+MEMF_PUBLIC,d1
CALLEXEC AllocMem
bne.s .cnt3
moveq #103,d0
rts
.cnt3
move.l d0,a2 ;a2 = StandardPacket
;===========================================================================
; Initialize a StandardPacket to send to process that controls the drive #
;===========================================================================
lea sp_Pkt(a2),a0
move.l a0,sp_Msg+MN+LN_NAME(a2);message node name = DOS packet
move.l a2,sp_Pkt+dp_Link(a2) ;pointer to exec message
sub.l a1,a1 ;own task (process)
CALL FindTask
move.l d0,a1
lea pr_MsgPort(a1),a0 ;own task message port is
move.l a0,d4
move.l a0,sp_Pkt+dp_Port(a2) ;=> ReplyPort for packet
moveq #ACTION_INHIBIT,d0 ;dospacket type/action (=INHIBIT)
move.l d0,sp_Pkt+dp_Type(a2)
;=========================
move.l d2,sp_Pkt+dp_Arg1(a2) ; dospacket Arg #
; 1 = disable drive task #
; 0 = enable drive task #
;=========================
;===========================================================================
; Get MessagePort of process that controls the drive (trackdisk?) #
;===========================================================================
move.l a3,d1 ;DrivePort = DeviceProc(drivename)
CALLDOS DeviceProc
bne.s .cnt1
move.l #218,d2
bra.s .end
.cnt1
;===========================================================================
; Now send the StandardPacket to the drive process #
;===========================================================================
move.l d0,a0 ;MessagePort of drive task
move.l a2,a1 ;packet (message)
CALLEXEC PutMsg
;===========================================================================
; Check result & exit #
;===========================================================================
moveq #0,d2 ;error code
;WAIT UNTIL WE GET A MESSAGE BACK
move.l d4,a0 ;our task's reply port
CALL WaitPort
cmp.l d0,a2 ;is it the right reply message?
beq.s .cnt2
moveq #100,d2 ;dos failure/wrong reply message
.cnt2
;REMOVE PACKET FROM LIST
move.l a2,a1 ;remove packet from list
CALLEXEC Remove
tst.l sp_Pkt+dp_Res1(a2) ;check result
bne.s .end
moveq #126,d0
.end
;EXIT WITH ERROR IN D0
move.l a2,a1 ;free memory for StandardPacket
moveq #sp_SIZEOF,d0
CALLEXEC FreeMem
move.l d2,d0
rts
;===========================================================================
_DOSBase dc.l 0
rawwindow dc.l 0
buffer dc.l 0
_DOSName dc.b "dos.library",0
rawwindowname dc.b "RAW:120/78/400/100/GetDrive",0
drivename dc.b "DF0:",0
not_mounted dc.b 10," Drive not mounted!",10,10,0
doserror dc.b 10," DOS Error. Packet reply failure!",10,10,0
drive_in_use dc.b 10," Can't get drive (in use?)",10,10,0
drive_disabled dc.b 10," Drive DF0: disabled.",10,10,0
press_key dc.b " Press any key to return...",10,10